//给你一个 m * n 的矩阵 mat，以及一个整数 k ，矩阵中的每一行都以非递减的顺序排列。 
//
// 你可以从每一行中选出 1 个元素形成一个数组。返回所有可能数组中的第 k 个 最小 数组和。 
//
// 
//
// 示例 1： 
//
// 输入：mat = [[1,3,11],[2,4,6]], k = 5
//输出：7
//解释：从每一行中选出一个元素，前 k 个和最小的数组分别是：
//[1,2], [1,4], [3,2], [3,4], [1,6]。其中第 5 个的和是 7 。  
//
// 示例 2： 
//
// 输入：mat = [[1,3,11],[2,4,6]], k = 9
//输出：17
// 
//
// 示例 3： 
//
// 输入：mat = [[1,10,10],[1,4,5],[2,3,6]], k = 7
//输出：9
//解释：从每一行中选出一个元素，前 k 个和最小的数组分别是：
//[1,1,2], [1,1,3], [1,4,2], [1,4,3], [1,1,6], [1,5,2], [1,5,3]。其中第 7 个的和是 9 。 
// 
//
// 示例 4： 
//
// 输入：mat = [[1,1,10],[2,2,9]], k = 7
//输出：12
// 
//
// 
//
// 提示： 
//
// 
// m == mat.length 
// n == mat.length[i] 
// 1 <= m, n <= 40 
// 1 <= k <= min(200, n ^ m) 
// 1 <= mat[i][j] <= 5000 
// mat[i] 是一个非递减数组 
// 
// Related Topics 堆 
// 👍 64 👎 0

/**
 * @author DaHuangXiao
 */
package leetcode.editor.cn;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Set;

public class FindTheKthSmallestSumOfAMatrixWithSortedRows {
    public static void main(String[] args) {
        Solution solution = new FindTheKthSmallestSumOfAMatrixWithSortedRows().new Solution();
    }

    //leetcode submit region begin(Prohibit modification and deletion)
    class Solution {
        private PriorityQueue<Item> pq = new PriorityQueue<>((o1, o2) -> o1.total - o2.total);
        private Set<String> visit = new HashSet<>();

        public int kthSmallest(int[][] mat, int k) {
            int sum = 0;
            for (int i = 0; i < mat.length; i++) {
                sum += mat[i][0];
            }
            Item first = new Item(new int[mat.length], sum);
            pq.offer(first);
            visit.add(Arrays.toString(first.indexs));
            while (k > 1) {
                Item cur = pq.poll();


                for (int j = 0; j < mat.length; j++) {
                    cur.indexs[j]++;
                    if (cur.indexs[j] < mat[j].length && !visit.contains(Arrays.toString(cur.indexs))) {

                        int[] pick = Arrays.copyOf(cur.indexs, cur.indexs.length);
                        Item newItem = new Item(pick, cur.total - mat[j][cur.indexs[j] - 1] + mat[j][cur.indexs[j]]);
                        visit.add(Arrays.toString(newItem.indexs));
                        pq.add(newItem);
                    }
                    cur.indexs[j]--;
                }
                k--;
            }
            return pq.peek().total;
        }

        class Item {
            private int[] indexs;
            private int total;

            public Item(int[] indexs, int total) {
                this.indexs = indexs;
                this.total = total;
            }
        }
    }
//leetcode submit region end(Prohibit modification and deletion)

}